from datetime import datetime
import io

from PIL import Image
from fastapi import UploadFile, HTTPException, Depends

from core.dependencies import get_minio_client
from db.models.users import UserDocument
from utils.minio_util import put_image, get_image_by_prefix
from utils.result import Result


class ImageService:
    def __init__(self,minio_client):
        self.minio_client = minio_client
        self.MAX_FILE_SIZE = 1024 * 1024 * 10

    async def upload_image(self,file:UploadFile,to_user_name:str,current_user:UserDocument):
        """服务层： 处理上传图片业务逻辑"""
        # 1、权限校验（业务逻辑）
        self._validate_user(current_user)

        # 2、文件类型校验（业务逻辑）
        self._validate_file(file)

        # 3.读取并且验证图片内容（业务逻辑）
        contents = await file.read()
        image_info = self._process_image(contents)

        #4.生成文件签名（业务逻辑）
        filename =self._generate_filename(username=current_user.username,to_username=to_user_name)

        #5.调用工具层对图片进行存储（技术细节）
        url = await put_image(contents,filename,self.minio_client)

        #6.返回结果
        data = {
            "url": url,
            "filename": filename,
            "mime": file.content_type,
            **image_info
        }
        return Result.success(data=data, msg="上传成功")

    async def get_image(self,filename,user: UserDocument):
        self._validate_user(user)
        urls = await get_image_by_prefix(prefix=filename, minio_client=self.minio_client)
        return Result.success(data=urls, msg="获取成功")

    def _validate_user(self,user: UserDocument):
        """校验用户是不是活跃用户"""
        if not user.is_active:
            raise HTTPException(status_code=403, detail="用户未激活")

    def _validate_file(self,file: UploadFile):
        """校验文件是不是合法文件"""
        if not file.content_type.startswith("image/"):
            raise HTTPException(status_code=400, detail="只允许上传图片文件")
        if file.size > self.MAX_FILE_SIZE:
            raise HTTPException(status_code=400, detail="图片大小超出限制")

    def _process_image(self,contents: bytes)->dict:
        """处理图片二进制数据，返回图片的基础信息"""
        try:
            image = Image.open(io.BytesIO(contents))
            image_info = {
                "size":image.size,
                "width":image.width,
                "height":image.height,
                "format":image.format,
                "mode":image.mode
            }
            return image_info
        except Exception as e:
            raise HTTPException(status_code=400,detail=f"无效的图片文件: {str(e)}")

    def _generate_filename(self,username,to_username):
        """生成文件签名"""
        timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
        return f"image_{username}_{to_username}_{timestamp}"

async def get_image_service(minio = Depends(get_minio_client)):
    return ImageService(minio)